/**
 * Lang模块 - 类型检查和类型转换
 * 借鉴Lodash的Lang理念
 */

/**
 * 检查是否为undefined或null
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为null或undefined
 */
export function isNil(value) {
  return value === null || value === undefined;
}

/**
 * 检查是否为null
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为null
 */
export function isNull(value) {
  return value === null;
}

/**
 * 检查是否为undefined
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为undefined
 */
export function isUndefined(value) {
  return value === undefined;
}

/**
 * 检查是否为字符串
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为字符串
 */
export function isString(value) {
  return typeof value === 'string';
}

/**
 * 检查是否为数字
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为数字
 */
export function isNumber(value) {
  return typeof value === 'number' && !isNaN(value);
}

/**
 * 检查是否为布尔值
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为布尔值
 */
export function isBoolean(value) {
  return typeof value === 'boolean';
}

/**
 * 检查是否为数组
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为数组
 */
export function isArray(value) {
  return Array.isArray(value);
}

/**
 * 检查是否为对象（不包括null和数组）
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为对象
 */
export function isObject(value) {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

/**
 * 检查是否为纯对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为纯对象
 */
export function isPlainObject(value) {
  if (!isObject(value)) return false;

  const proto = Object.getPrototypeOf(value);
  if (proto === null) return true;

  const Ctor = Object.prototype.hasOwnProperty.call(proto, 'constructor') && proto.constructor;
  return typeof Ctor === 'function' && Ctor === Object;
}

/**
 * 检查是否为函数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为函数
 */
export function isFunction(value) {
  return typeof value === 'function';
}

/**
 * 检查是否为Date对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Date
 */
export function isDate(value) {
  return value instanceof Date && !isNaN(value.getTime());
}

/**
 * 检查是否为正则表达式
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为正则表达式
 */
export function isRegExp(value) {
  return value instanceof RegExp;
}

/**
 * 检查是否为Error对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Error
 */
export function isError(value) {
  return value instanceof Error;
}

/**
 * 检查是否为Symbol
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Symbol
 */
export function isSymbol(value) {
  return typeof value === 'symbol';
}

/**
 * 检查是否为整数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为整数
 */
export function isInteger(value) {
  return Number.isInteger(value);
}

/**
 * 检查是否为安全整数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为安全整数
 */
export function isSafeInteger(value) {
  return Number.isSafeInteger(value);
}

/**
 * 检查是否为有限数
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为有限数
 */
export function isFinite(value) {
  return typeof value === 'number' && Number.isFinite(value);
}

/**
 * 检查是否为NaN
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为NaN
 */
export function isNaN(value) {
  return typeof value === 'number' && Number.isNaN(value);
}

/**
 * 检查是否为类数组对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为类数组
 */
export function isArrayLike(value) {
  return value != null && typeof value !== 'function' && isLength(value.length);
}

/**
 * 检查是否为类数组对象（排除字符串）
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为类数组对象
 */
export function isArrayLikeObject(value) {
  return isArrayLike(value) && typeof value === 'object';
}

/**
 * 检查是否为有效的数组长度
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为有效长度
 */
export function isLength(value) {
  return typeof value === 'number' && value >= 0 && value <= Number.MAX_SAFE_INTEGER && value % 1 === 0;
}

/**
 * 检查是否为空（null, undefined, '', [], {}）
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为空
 */
export function isEmpty(value) {
  if (value == null) return true;
  if (isArrayLike(value)) return value.length === 0;
  if (isObject(value)) return Object.keys(value).length === 0;
  return false;
}

/**
 * 检查值是否相等（深度比较）
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} 是否相等
 */
export function isEqual(value, other) {
  if (value === other) return true;

  if (value == null || other == null) return value === other;

  if (typeof value !== typeof other) return false;

  if (typeof value !== 'object') return value === other;

  if (Array.isArray(value) !== Array.isArray(other)) return false;

  if (Array.isArray(value)) {
    if (value.length !== other.length) return false;
    return value.every((item, index) => isEqual(item, other[index]));
  }

  const keys1 = Object.keys(value);
  const keys2 = Object.keys(other);

  if (keys1.length !== keys2.length) return false;

  return keys1.every(key => keys2.includes(key) && isEqual(value[key], other[key]));
}

/**
 * 检查对象是否匹配源对象的属性
 * @param {Object} object 要检查的对象
 * @param {Object} source 源对象
 * @returns {boolean} 是否匹配
 */
export function isMatch(object, source) {
  if (object === source) return true;
  if (source == null || object == null) return object === source;

  const keys = Object.keys(source);

  for (const key of keys) {
    if (!isEqual(object[key], source[key])) {
      return false;
    }
  }

  return true;
}

/**
 * 转换为数组
 * @param {any} value 要转换的值
 * @returns {Array} 数组
 */
export function toArray(value) {
  if (!value) return [];
  if (Array.isArray(value)) return value.slice();
  if (typeof value === 'string') return value.split('');
  if (typeof value === 'object') return Object.values(value);
  return [value];
}

/**
 * 转换为字符串
 * @param {any} value 要转换的值
 * @returns {string} 字符串
 */
export function toString(value) {
  if (value == null) return '';
  if (typeof value === 'string') return value;
  if (Array.isArray(value)) return value.map(toString).join(',');
  if (isSymbol(value)) return value.toString();
  return String(value);
}

/**
 * 转换为数字
 * @param {any} value 要转换的值
 * @returns {number} 数字
 */
export function toNumber(value) {
  if (typeof value === 'number') return value;
  if (isSymbol(value)) return NaN;
  if (typeof value === 'string') {
    const trimmed = value.trim();
    if (trimmed === '') return 0;
    return Number(trimmed);
  }
  if (typeof value === 'boolean') return value ? 1 : 0;
  if (value == null) return 0;
  return Number(value);
}

/**
 * 转换为整数
 * @param {any} value 要转换的值
 * @returns {number} 整数
 */
export function toInteger(value) {
  const num = toNumber(value);
  if (!isFinite(num)) return num === Infinity ? Number.MAX_VALUE : num === -Infinity ? -Number.MAX_VALUE : 0;
  return Math.floor(Math.abs(num)) * (num < 0 ? -1 : 1);
}

/**
 * 转换为安全整数
 * @param {any} value 要转换的值
 * @returns {number} 安全整数
 */
export function toSafeInteger(value) {
  const num = toInteger(value);
  if (num < Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER;
  if (num > Number.MAX_SAFE_INTEGER) return Number.MAX_SAFE_INTEGER;
  return num;
}

/**
 * 转换为有限数
 * @param {any} value 要转换的值
 * @returns {number} 有限数
 */
export function toFinite(value) {
  const num = toNumber(value);
  if (!isFinite(num)) return num === Infinity ? Number.MAX_VALUE : num === -Infinity ? -Number.MAX_VALUE : 0;
  return num;
}

/**
 * 转换为纯对象
 * @param {any} value 要转换的值
 * @returns {Object} 纯对象
 */
export function toPlainObject(value) {
  if (value == null) return {};
  if (typeof value !== 'object') return {};

  const result = {};
  for (const key in value) {
    result[key] = value[key];
  }
  return result;
}

/**
 * 克隆值
 * @param {any} value 要克隆的值
 * @returns {any} 克隆后的值
 */
export function clone(value) {
  if (value === null || typeof value !== 'object') return value;
  if (value instanceof Date) return new Date(value.getTime());
  if (value instanceof RegExp) return new RegExp(value);
  if (Array.isArray(value)) return value.slice();
  if (typeof value === 'object') return { ...value };
  return value;
}

/**
 * 深度克隆值
 * @param {any} value 要克隆的值
 * @returns {any} 克隆后的值
 */
export function cloneDeep(value) {
  if (value === null || typeof value !== 'object') return value;
  if (value instanceof Date) return new Date(value.getTime());
  if (value instanceof RegExp) return new RegExp(value);
  if (Array.isArray(value)) return value.map(item => cloneDeep(item));

  if (typeof value === 'object') {
    const cloned = {};
    Object.keys(value).forEach(key => {
      cloned[key] = cloneDeep(value[key]);
    });
    return cloned;
  }

  return value;
}

/**
 * 比较两个值的大小
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} value > other
 */
export function gt(value, other) {
  return value > other;
}

/**
 * 比较两个值的大小
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} value >= other
 */
export function gte(value, other) {
  return value >= other;
}

/**
 * 比较两个值的大小
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} value < other
 */
export function lt(value, other) {
  return value < other;
}

/**
 * 比较两个值的大小
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} value <= other
 */
export function lte(value, other) {
  return value <= other;
}

/**
 * 严格相等比较（SameValueZero）
 * @param {any} value 值1
 * @param {any} other 值2
 * @returns {boolean} 是否相等
 */
export function eq(value, other) {
  return value === other || (value !== value && other !== other); // NaN === NaN
}

/**
 * 检查类型
 * @param {any} value 要检查的值
 * @returns {string} 类型字符串
 */
export function getType(value) {
  if (value === null) return 'null';
  if (value === undefined) return 'undefined';
  if (Array.isArray(value)) return 'array';
  if (value instanceof Date) return 'date';
  if (value instanceof RegExp) return 'regexp';
  if (value instanceof Error) return 'error';
  return typeof value;
}

/**
 * 检查是否为Map
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Map
 */
export function isMap(value) {
  return value instanceof Map;
}

/**
 * 检查是否为Set
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Set
 */
export function isSet(value) {
  return value instanceof Set;
}

/**
 * 检查是否为WeakMap
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为WeakMap
 */
export function isWeakMap(value) {
  return value instanceof WeakMap;
}

/**
 * 检查是否为WeakSet
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为WeakSet
 */
export function isWeakSet(value) {
  return value instanceof WeakSet;
}

/**
 * 检查是否为Promise
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Promise
 */
export function isPromise(value) {
  return value instanceof Promise || (value && typeof value.then === 'function');
}

/**
 * 检查是否为类型化数组
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为类型化数组
 */
export function isTypedArray(value) {
  return value instanceof Int8Array ||
         value instanceof Uint8Array ||
         value instanceof Uint8ClampedArray ||
         value instanceof Int16Array ||
         value instanceof Uint16Array ||
         value instanceof Int32Array ||
         value instanceof Uint32Array ||
         value instanceof Float32Array ||
         value instanceof Float64Array;
}

/**
 * 检查是否为Buffer
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Buffer
 */
export function isBuffer(value) {
  return typeof Buffer !== 'undefined' && value instanceof Buffer;
}

/**
 * 检查是否为Arguments对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为Arguments
 */
export function isArguments(value) {
  return Object.prototype.toString.call(value) === '[object Arguments]';
}
